package com.atguigu.spzx.cloud.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.atguigu.spzx.cloud.model.entity.Order;
import com.atguigu.spzx.cloud.model.entity.User;
import com.atguigu.spzx.cloud.feign.api.client.UserClient;
import com.atguigu.spzx.cloud.order.mapper.OrderMapper;
import com.atguigu.spzx.cloud.order.service.OrderService;
import jakarta.annotation.Resource;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper ;
    @Resource
    RestTemplate restTemplate;
    //springcloud提供的  可以根据服务注册到注册中心的名称拉取它的地址列表
    @Resource
    DiscoveryClient discoveryClient;
    @Resource
    UserClient userClient;
    @Override
    public Order findOrderByOrderId(Long orderId) {
        //修改需求：查询订单 以及订单的用户数据一起返回
        Order order = orderMapper.findOrderByOrderId(orderId);
//        User user = getUserByHttpClient(order.getUserId());
//        User user = getUserByRestTemplate(order.getUserId());
        User user = userClient.findUserByUserId(order.getUserId());
        order.setUser(user);
        return order;
    }
    private User getUserByRestTemplate(Long userId) {

        return restTemplate.getForObject("http://spzx-cloud-user/api/user/findUserByUserId/{0}",
                User.class , userId);
    }




    /*
        HttpClient的问题：
            1、请求地址写死了
                切换环境时还需要手动修改
            2、服务多实例启动时 无法负载均衡(将请求分摊到不同的实例上处理)
            3、返回结果需要我们手动解析：
                状态码判断、响应体数据类型转换...
        改造1：我们可以使用springweb提供的RestTemplate 发起网络请求，它对HttpClient进行了简单的封装 简化了网络请求操作
            使用步骤：
                1、将RestTemplate对象注入到容器中
                2、自动装配
                3、使用它发起网络请求


     */
    private User getUserByHttpClient(Long userId) {
        try {
            //1、创建一个请求客户端：类似浏览器
            DefaultHttpClient httpClient = new DefaultHttpClient();
            //2、创建一个请求对象：封装请求参数  地址+请求方式+请求参数(请求报文)
            HttpGet request = new HttpGet("http://localhost:10100/api/user/findUserByUserId/"+userId);
            //3、使用客户端 用请求对象配置发起网络请求 得到响应结果(响应报文)
            CloseableHttpResponse response = httpClient.execute(request);
            //4、解析响应结果
            System.out.println("响应报文状态码："+response.getStatusLine().getStatusCode());

            //获取响应体
            String result = EntityUtils.toString(response.getEntity(), "UTF-8");
            //将json转为User对象
            return JSON.parseObject(result,User.class);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //使用discoveryClient实现负载均衡远程调用
    private User getUserByRestTemplate2(Long userId) {
        ServiceInstance server = chooseServer("spzx-cloud-user");
        String host = server.getHost();
        int port = server.getPort();
        return restTemplate.getForObject("http://"+host+":"+port+"/api/user/findUserByUserId/{0}",
                User.class , userId);
    }
    int count = 0;
    //使用服务名到注册中心拉取一组地址列表 选择一个返回
    private ServiceInstance chooseServer(String appName){

        List<ServiceInstance> instances = discoveryClient.getInstances("spzx-cloud-user");
        if(CollectionUtils.isEmpty(instances)){
            return null;
        }
        //选择一个合适的返回 用来处理请求
        //自己编写一个轮询的负载均衡策略
        ServiceInstance instance = instances.get(count % instances.size());
        count++;
        return instance;
    }
}